home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / CNews / Source / relay / transmit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-28  |  7.3 KB  |  293 lines

  1. /*
  2.  * transmit - transmit incoming articles to neighbouring machines
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <sys/types.h>
  8. #include "libc.h"
  9. #include "news.h"
  10. #include "config.h"
  11. #include "headers.h"
  12. #include "active.h"
  13. #include "article.h"
  14. #include "msgs.h"
  15. #include "ngmatch.h"
  16. #include "system.h"
  17. #include "trbatch.h"
  18. #include "transmit.h"
  19.  
  20. /* forwards */
  21. FORWARD boolean oktransmit();
  22. FORWARD void ejaculate(), trappend();
  23. FORWARD char *pctsubst();
  24.  
  25. /* private */
  26. static boolean debug = NO;
  27.  
  28. void
  29. transdebug(state)
  30. boolean state;
  31. {
  32.     debug = state;
  33. }
  34.  
  35. /*
  36.  * For each system in "sys" other than this one,
  37.  * transmit this article when its ng pattern matches
  38.  * art->h.h_distr (which may be just a copy of art->h.h_ngs).
  39.  */
  40. void
  41. transmit(art, exclude)
  42. register struct article *art;
  43. char *exclude;                    /* no copy to this site */
  44. {
  45.     register struct system *sys;
  46.     register int bsysno = 0;    /* ordinal # of batch sys entry */
  47.  
  48.     rewndsys();
  49.     if (debug)
  50.         (void) fprintf(stderr, "just rewound sys file\n");
  51.     while ((sys = nextsys()) != NULL) {
  52.         if (debug) {
  53.             (void) fprintf(stderr, "sy_name=%s sy_ngs=",
  54.                 sys->sy_name);
  55.             ngprint(sys->sy_trngs, stderr);
  56.             (void) fprintf(stderr, " sy_distr=");
  57.             ngprint(sys->sy_trdistr, stderr);
  58.             (void) fprintf(stderr, "\n");
  59.         }
  60.         if (oktransmit(art, sys, exclude))
  61.             ejaculate(art, sys, bsysno);
  62.         if (sys->sy_flags&FLG_BATCH)
  63.             ++bsysno;
  64.     }
  65.     if (debug)
  66.         (void) fprintf(stderr, "just finished reading sys file\n");
  67. }
  68.  
  69. /*
  70.  * Is it okay to send the article corresponding to "art" to site "sys",
  71.  * excluding site "exclude"?
  72.  *
  73.  * If L(n) flag is on, must have been posted within n hops of here.
  74.  * Never send to this site, nor the "exclude" site, nor any site with a host
  75.  * in sys->sy_excl named in Path:, nor any site named in Path:.
  76.  *
  77.  * Newsgroups: must match sys's subscription list.
  78.  * Distribution: must match sys's distribution list.  (RFC 850 is wrong:
  79.  * Distribution:s are *not* patterns, they are lists.  See RFC 1036.)
  80.  *
  81.  * If m flag is on, group(s) must be moderated; if u flag is on,
  82.  * must be unmoderated.  (If both are on, act as if neither is on.)
  83.  */
  84. STATIC boolean
  85. oktransmit(art, sys, exclude)
  86. register struct article *art;
  87. register struct system *sys;
  88. char *exclude;                /* no copy to him */
  89. {
  90.     register int flags = sys->sy_flags;
  91.     register char *site = sys->sy_name;
  92.     register char *path;
  93.     register int result = YES;
  94.     static char *canpath;
  95.     static long lastid = -1;
  96.  
  97.     if (art->a_id != lastid) {    /* new article? */
  98.         lastid = art->a_id;
  99.         nnfree(&canpath);
  100.         canpath = canonpath(art->h.h_path, art->h.h_approved, art->h.h_sender);
  101. #ifdef notdef            /* DEBUG */
  102.         fprintf(stderr, "path=%s canonpath=%s\n", art->h.h_path,
  103.             canpath);
  104. #endif
  105.     }
  106.     path = canpath;
  107.     if (flags&FLG_LOCAL && hopcount(path) > sys->sy_lochops ||
  108.         STREQ(hostname(), site) ||
  109.         exclude != NULL && STREQ(exclude, site) || hostin(site, path) ||
  110.         sys->sy_excl != NULL && anyhostin(sys->sy_excl, path) ||
  111.         !ngpatmat(sys->sy_trngs, art->h.h_ngs) ||
  112.         !ngpatmat(sys->sy_trdistr, art->h.h_distr))
  113.         result = NO;
  114.     else if (flags&(FLG_MOD|FLG_UNMOD)) {    /* u, m flag selection */
  115.         if ((flags&(FLG_MOD|FLG_UNMOD)) != (FLG_MOD|FLG_UNMOD))
  116.             result = (flags&FLG_MOD? moderated(art->h.h_ngs):
  117.                         !moderated(art->h.h_ngs));
  118.     }
  119.     return result;
  120. }
  121.  
  122. /*
  123.  * Send the article denoted by art to the system denoted by sys.
  124.  *
  125.  * When a filename is needed, we use the first one in art->a_files
  126.  * rather than art->a_tmpf because we want a permanent name.
  127.  *
  128.  * Side-effect: prints the system name on stdout for logging.
  129.  */
  130. STATIC void
  131. ejaculate(art, sys, bsysno)
  132. register struct article *art;
  133. register struct system *sys;
  134. int bsysno;
  135. {
  136.     register char *fullname;
  137.     register char *filename = first(art->a_files);
  138.  
  139.     if (debug)
  140.         (void) fprintf(stderr, "transmitting %s to %s\n",
  141.             art->h.h_msgid, sys->sy_name);
  142.         (void) printf(" %s", sys->sy_name);    /* logging */
  143.  
  144.     mkfilenm(filename);
  145.     fullname = strsave(artfile(filename));    /* N.B.: relative path */
  146.     free(filename);
  147.  
  148.     if (sys->sy_flags&FLG_BATCH)
  149.             trbatch(art, sys, fullname, bsysno);
  150.     else
  151.         trcmd(art, sys, fullname);
  152.     free(fullname);
  153. }
  154.  
  155. /*
  156.  * Execute sys->sy_cmd with the current article as stdin
  157.  * and filename substituted for %s in sys->sy_cmd (if any).
  158.  *
  159.  * Search path includes $NEWSCTL/bin and $NEWSBIN/relay.
  160.  * redirect stdin to prevent consuming my stdin & so cmd's stdin
  161.  * is filename by default.
  162.  */
  163. void
  164. trcmd(art, sys, filename)
  165. struct article *art;
  166. struct system *sys;
  167. char *filename;
  168. {
  169.     register char *cmd, *substcmd;
  170.     int exitstat;
  171.     char *s1, *s2, *s3, *pfx;
  172.     static char *ctlcmd = NULL, *bincmd = NULL;
  173.  
  174.     if (ctlcmd == NULL)
  175.         ctlcmd = strsave(ctlfile("bin"));
  176.     if (bincmd == NULL)
  177.         bincmd = strsave(binfile("relay"));
  178.  
  179.     s1 = str3save("PATH=", ctlcmd, ":");
  180.     s2 = str3save(bincmd, ":", newspath());
  181.     s3 = str3save("; <", filename, " (");
  182.     pfx = str3save(s1, s2, s3);
  183.     free(s1);
  184.     free(s2);
  185.     free(s3);
  186.  
  187.     substcmd = pctsubst(sys->sy_cmd, filename);
  188.     if (substcmd == NULL)
  189.         art->a_status |= ST_DROPPED;
  190.     else {
  191.         cmd = str3save(pfx, substcmd, ")");
  192.         free(substcmd);
  193.     
  194.         exitstat = system(cmd);
  195.         if (exitstat != 0) {
  196.             art->a_status |= ST_DROPPED;
  197.             (void) fprintf(stderr, "%s: `", progname);
  198.             (void) fputs(cmd, stderr);
  199.             (void) fprintf(stderr, "' returned exit status 0%o\n",
  200.                 exitstat);
  201.         }
  202.         free(cmd);
  203.     }
  204.     free(pfx);
  205. }
  206.  
  207. /*
  208.  * We avoid sprintf if syscmd contains no %, thus avoiding the 128-byte
  209.  * restriction on printf output (see printf(3) BUGS, at least in V7).
  210.  */
  211. STATIC char *                    /* malloced storage */
  212. pctsubst(cmd, file)    /* copy cmd, replace %s in it with file, return copy */
  213. char *cmd, *file;
  214. {
  215.     register char *copy = NULL, *percent, *pcent2 = NULL;
  216.     register int format;
  217.  
  218.     percent = strchr(cmd, '%');
  219.     if (percent == NULL)
  220.         copy = strsave(cmd);
  221.     else {
  222.         ++percent;
  223.         format = *percent;
  224.         if (format != '\0')
  225.             percent++;
  226.         pcent2 = strchr(percent, '%');
  227.         if (pcent2 != NULL)
  228.             (void) fprintf(stderr, "%s: `%s' contains two %%'s\n",
  229.                 progname, cmd);
  230.         else if (format != 's' && format != '%')
  231.             (void) fprintf(stderr,
  232.                 "%s: `%s' contains %%%c, not %%s\n",
  233.                 progname, cmd, format);
  234.         else {
  235.             copy = nemalloc((unsigned)
  236.                     (strlen(cmd) + strlen(file) + SIZENUL));
  237.             (void) sprintf(copy, cmd, file);
  238.         }
  239.     }
  240.     return copy;
  241. }
  242.  
  243. /*
  244.  * Append "filename" to sys->sy_cmd.  bsysno is the ordinal # of this batch
  245.  * sys line.  If bsysno is low enough, use the batchfile cache of batch file
  246.  * descriptors.
  247.  */
  248. void
  249. trbatch(art, sys, filename, bsysno)
  250. register struct article *art;
  251. struct system *sys;
  252. char *filename;
  253. register int bsysno;
  254. {
  255.     register struct batchfile *bf = bfopen(sys->sy_cmd, bsysno);
  256.  
  257.     if (bf == NULL || bf->bf_str == NULL)
  258.         art->a_status |= ST_DROPPED;
  259.     else {
  260.         trappend(art, sys, bf, filename);
  261.         art->a_status |= bffkclose(bsysno);
  262.     }
  263. }
  264.  
  265. /*
  266.  * package up article filename, message-id, size, batch file name
  267.  * and formatting flags for batch file "bf".
  268.  */
  269. STATIC void
  270. trappend(art, sys, bf, artname)
  271. register struct article *art;
  272. register struct system *sys;
  273. struct batchfile *bf;
  274. char *artname;
  275. {
  276.     int flag = (sys->sy_flags&FLG_IHAVE? 'I':
  277.            (sys->sy_flags&FLG_NBATCH? 'n':
  278.            (sys->sy_flags&FLG_SZBATCH? 'f': 'F')));
  279.  
  280.     if (!bfappend(bf, flag, sys->sy_cmd,
  281.         artname, art->h.h_msgid, art->a_charswritten))
  282.         fulldisk(art, bf->bf_name);
  283. }
  284.  
  285. /*
  286.  * really close all the open batch files
  287.  */
  288. statust
  289. trclose()
  290. {
  291.     return bfrealclose();
  292. }
  293.